package com.ruicar.afs.cloud.basic.sync;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.basic.api.dto.ProductInfoDTO;
import com.ruicar.afs.cloud.basic.api.dto.ProductPlanDataVo;
import com.ruicar.afs.cloud.basic.api.product.feign.ProductServiceFeign;
import com.ruicar.afs.cloud.basic.common.entity.*;
import com.ruicar.afs.cloud.basic.common.service.*;
import com.ruicar.afs.cloud.basic.proceeds.mq.dto.*;
import com.ruicar.afs.cloud.basic.proceeds.pay.entity.BasicAutoPaymentConfig;
import com.ruicar.afs.cloud.basic.proceeds.pay.entity.BasicPaymentBank;
import com.ruicar.afs.cloud.basic.proceeds.pay.entity.BasicPaymentPool;
import com.ruicar.afs.cloud.basic.proceeds.pay.entity.BasicPaymentPoolDetails;
import com.ruicar.afs.cloud.basic.proceeds.pay.service.BasicAutoPaymentConfigService;
import com.ruicar.afs.cloud.basic.proceeds.pay.service.BasicPaymentBankService;
import com.ruicar.afs.cloud.basic.proceeds.pay.service.BasicPaymentPoolDetailsService;
import com.ruicar.afs.cloud.basic.proceeds.pay.service.BasicPaymentPoolService;
import com.ruicar.afs.cloud.bizcommon.algorithm.service.FinanceCalculatorService;
import com.ruicar.afs.cloud.bizcommon.business.bean.AfsRepaymentInfo;
import com.ruicar.afs.cloud.bizcommon.business.dto.CalculatorDTO;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinRentAdjustDetails;
import com.ruicar.afs.cloud.bizcommon.business.vo.RepaymentPlanVO;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.uid.UidGenerator;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author: Lee
 * @date: 2020/5/11 19:39
 * @description: 贷前数据同步-借据、费用、还款计划类
 */
@AllArgsConstructor
@Component
@Slf4j
public class ApplyLoanDataCostSubHandler{

	private final BasicFinancialAgreementService basicFinancialAgreementService;
	private final BasicFinancingItemsService basicFinancingItemsService;
	private final BasicRepaymentPlanService basicRepaymentPlanService;
	private final BasicAssetsRepaymentPlanService basicAssetsRepaymentPlanService;
	private final BasicInterestAmortizePlanService basicInterestAmortizePlanService;
	private final BasicDebitInfoService basicDebitInfoService;
	private final BasicDiscountDetailsService basicDiscountDetailsService;
	private final BasicBankCardService basicBankCardService;
	private final BasicProductParamService basicProductParamService;
	private final BasicRentAdjustDetailsService basicRentAdjustDetailsService;
	private final ProductServiceFeign productFeign;
	private final FinanceCalculatorService financeCalculatorService;
	private final UidGenerator uidGenerator;
	private final BasicCostAmortizePlanService amortizePlanService;
	private final BasicProductGraceConfigService productGraceConfigService;
	private final BasicSpecialGraceConfigService specialGraceConfigService;
	private final BasicCompanyGraceConfigService companyGraceConfigService;
	private final BasicPaymentPoolDetailsService poolDetailsService;
	private final BasicAutoPaymentConfigService autoPaymentConfigService;
	private final BasicAutoPaymentConfigService basicAutoPaymentConfigService;
	private final BasicPaymentPoolService paymentPoolService;
	private final BasicPaymentBankService paymentBankService;
	private final ApplyLoanDataChannelSubHandler applyLoanDataChannelSubHandler;

	/**
	 * 金融协议表转换成计算类
	 */
	public CalculatorDTO buildCalculatorDTO(BasicFinancialAgreement basicFinancialAgreement) {
		CalculatorDTO calculatorDTO = new CalculatorDTO();
		calculatorDTO.setLoanAmt(basicFinancialAgreement.getLoanAmt());
		calculatorDTO.setLoanTerm(basicFinancialAgreement.getLoanTerm());
		calculatorDTO.setContractAmt(basicFinancialAgreement.getContractAmt());
		calculatorDTO.setProductId(valueOf(basicFinancialAgreement.getProductId()));
		calculatorDTO.setDownPayScale(basicFinancialAgreement.getDownPayScale());
		//默认不贴息
		DiscountType discountType = DiscountType.NO;
		if(basicFinancialAgreement.getDiscountType()!=null)
			discountType = basicFinancialAgreement.getDiscountType();
		calculatorDTO.setDiscountType(AfsEnumUtil.key(discountType));
		calculatorDTO.setDiscountAmt(basicFinancialAgreement.getTotalDiscountAmt());
		calculatorDTO.setCustRate(basicFinancialAgreement.getCustRate());
		calculatorDTO.setSettleRate(basicFinancialAgreement.getSettleRate());
		calculatorDTO.setTailPayAmt(basicFinancialAgreement.getTailPayAmt());
		return calculatorDTO;
	}
	/**
	 * 获取宽限期 金融产品宽限期>地区宽限期>公司层配置的宽限期
	 */
	public Integer getGracePeriodDays(String productId,String channelCity){
		// 产品配置的宽限期
		BasicProductGraceConfig graceConfig = productGraceConfigService
				.getOne(Wrappers.<BasicProductGraceConfig>lambdaQuery()
						.eq(BasicProductGraceConfig::getProductNo, productId)
						.eq(BasicProductGraceConfig::getStatus, ValidOrInvalidEnum.valid));
		if (!ObjectUtils.isEmpty(graceConfig) && graceConfig.getGracePeriodDays() != null) {
			return graceConfig.getGracePeriodDays();
		}

		// 地区配置的宽限期
		BasicSpecialGraceConfig specialGraceConfig = specialGraceConfigService
				.getOne(Wrappers.<BasicSpecialGraceConfig>lambdaQuery()
						.eq(BasicSpecialGraceConfig::getLicensedAreaCode,channelCity)
						.eq(BasicSpecialGraceConfig::getStatus, ValidOrInvalidEnum.valid));
		if (!ObjectUtils.isEmpty(specialGraceConfig) && specialGraceConfig.getGracePeriodDays() != null) {
			return specialGraceConfig.getGracePeriodDays();
		}


		// 公司层配置的宽限期
		BasicCompanyGraceConfig companyGraceConfig = Optional
				.ofNullable(companyGraceConfigService.list()).map(con -> con.get(0))
				.orElse(new BasicCompanyGraceConfig());
		if (!ObjectUtils.isEmpty(companyGraceConfig) && companyGraceConfig.getGracePeriod() != null) {
			return companyGraceConfig.getGracePeriod();
		}
		return null;
	}
	/**
	 * 构建计算类DTO
	 */
	private Map<String,CalculatorDTO> buildCalPlanMap(ApplyLoanDataMessage entity,BasicFinancialAgreement basicFinancialAgreement,
													  Map<String,CalculatorDTO> calculatorDTOs) {
		//车款还款计划计算DTO
		CalculatorDTO carDto = null;
		//附加贷还款计划计算DTO
		CalculatorDTO addProductDto = null;
		if (basicFinancialAgreement.getCostType() == AssetTypeEnum.CAR_AMT) {
			carDto = buildCalculatorDTO(basicFinancialAgreement);
			carDto.setAddAmt(basicFinancialAgreement.getAddAmt());
			//"01"表示车款
			carDto.setCostType("01");
			if (!ObjectUtils.isEmpty(entity.getFinRentAdjustDetailsList())) { // 任意贷款 增加租金明细

				List<FinRentAdjustDetails> details = (List<FinRentAdjustDetails>) ApplyLoanDataProcessor
						.converBean(entity.getFinRentAdjustDetailsList(), FinRentAdjustDetails.class);
				carDto.setRentList(details);
			}
			calculatorDTOs.put("01",carDto);
		} else {
			addProductDto = buildCalculatorDTO(basicFinancialAgreement);
			//"02"表示附加贷款
			addProductDto.setCostType("02");
			//carDto.setAddAmt(basicFinancialAgreement.getLoanAmt());//顺序不对怎么办？？？？？在外面单独处理map
			calculatorDTOs.put("02",addProductDto);

		}
		if(calculatorDTOs.size()>0 && calculatorDTOs.get("01")!= null && calculatorDTOs.get("02")!=null)
			calculatorDTOs.get("01").setAddAmt(calculatorDTOs.get("02").getAddAmt());
		return calculatorDTOs;
	}
	/**
	 * 保存产品参数表
	 */
	private BigDecimal saveBasicProductParam(Map<String,CalculatorDTO> calculatorDTOs,ApplyLoanDataMessage entity) {
		ContractMainInfoDTO mainInfo = entity.getMainInfo();
		// 税率
		BigDecimal taxRate = BigDecimal.ZERO;
		CalculatorDTO carDto = calculatorDTOs.get("01");
		CalculatorDTO addProductDto = calculatorDTOs.get("02");
		// 获取产品及还款计划
		ProductInfoDTO productInfoDto = ProductInfoDTO.builder().id(Long.parseLong(carDto.getProductId()))
				.build();

		List<BasicProductParam> productParamList = new ArrayList<>();

		IResponse<List<ProductPlanDataVo>> planDataVo = productFeign
				.getProductPlanDataByProductId(productInfoDto); // 获取贷后产品参数
		for (ProductPlanDataVo planData : planDataVo.getData()) {
			BasicProductParam productParam = new BasicProductParam();

			productParam.setContractNo(mainInfo.getContractNo());
			productParam.setProductId(Long.parseLong(carDto.getProductId()));
			productParam.setAtomKey(
					(ProductAtomEnum) AfsEnumUtil.getEnum(planData.getProductAtomKey(), ProductAtomEnum.class));
			productParam.setAtomValue(planData.getAtomValue());

			if (AfsEnumUtil.key(ProductAtomEnum.TAX_RATE).equals(planData.getProductAtomKey())) { // 税率
				taxRate = new BigDecimal(planData.getAtomValue());
			}
			productParamList.add(productParam);
		}


		calculatorDTOs.entrySet().stream().forEach(s -> {
			CalculatorDTO calculatorDTO = s.getValue();
			if(EmptyUtils.isNotEmpty(calculatorDTO.getStep())) {
				BasicProductParam step = new BasicProductParam();
				step.setContractNo(mainInfo.getContractNo());
				step.setProductId(Long.parseLong(calculatorDTO.getProductId()));
				step.setAtomKey(ProductAtomEnum.STEP);
				step.setAtomValue(valueOf(calculatorDTO.getStep()));
				productParamList.add(step);
			}
			if(EmptyUtils.isNotEmpty(calculatorDTO.getStepPercent())) {
				BasicProductParam stepPercent = new BasicProductParam();
				stepPercent.setProductId(Long.parseLong(calculatorDTO.getProductId()));
				stepPercent.setContractNo(mainInfo.getContractNo());
				stepPercent.setAtomKey(ProductAtomEnum.STE_PERCENT);
				stepPercent.setAtomValue(valueOf(calculatorDTO.getStepPercent()));
				productParamList.add(stepPercent);
			}
			if(EmptyUtils.isNotEmpty(calculatorDTO.getBallonLoanType())) {
				BasicProductParam ballonLoanType = new BasicProductParam();
				ballonLoanType.setProductId(Long.parseLong(calculatorDTO.getProductId()));
				ballonLoanType.setContractNo(mainInfo.getContractNo());
				ballonLoanType.setAtomKey(ProductAtomEnum.BALLON_LOAN_TYPE);
				ballonLoanType.setAtomValue(valueOf(calculatorDTO.getBallonLoanType()));
				productParamList.add(ballonLoanType);
			}
			if(EmptyUtils.isNotEmpty(calculatorDTO.getPeroids())) {
				BasicProductParam peroids = new BasicProductParam();
				peroids.setProductId(Long.parseLong(calculatorDTO.getProductId()));
				peroids.setContractNo(mainInfo.getContractNo());
				peroids.setAtomKey(ProductAtomEnum.PEROIDS);
				peroids.setAtomValue(valueOf(calculatorDTO.getPeroids()));
				productParamList.add(peroids);
			}
			if(EmptyUtils.isNotEmpty(calculatorDTO.getMoney())) {
				BasicProductParam money = new BasicProductParam();
				money.setProductId(Long.parseLong(calculatorDTO.getProductId()));
				money.setContractNo(mainInfo.getContractNo());
				money.setAtomKey(ProductAtomEnum.MONEY);
				money.setAtomValue(valueOf(calculatorDTO.getMoney()));
				productParamList.add(money);
			}
			if(EmptyUtils.isNotEmpty(calculatorDTO.getStructuredMonth())) {
				BasicProductParam structuredMonth = new BasicProductParam();
				structuredMonth.setProductId(Long.parseLong(calculatorDTO.getProductId()));
				structuredMonth.setContractNo(mainInfo.getContractNo());
				structuredMonth.setAtomKey(ProductAtomEnum.STRUCTURED_MONTH);
				structuredMonth.setAtomValue(valueOf(calculatorDTO.getStructuredMonth()));
				productParamList.add(structuredMonth);
			}
			if(EmptyUtils.isNotEmpty(calculatorDTO.getStructuredType())) {
				BasicProductParam structuredType = new BasicProductParam();
				structuredType.setProductId(Long.parseLong(calculatorDTO.getProductId()));
				structuredType.setContractNo(mainInfo.getContractNo());
				structuredType.setAtomKey(ProductAtomEnum.STRUCTURED_TYPE);
				structuredType.setAtomValue(valueOf(calculatorDTO.getStructuredType()));
				productParamList.add(structuredType);
			}
			if(EmptyUtils.isNotEmpty(calculatorDTO.getStructuredMoney())) {
				BasicProductParam structuredMoney = new BasicProductParam();
				structuredMoney.setProductId(Long.parseLong(calculatorDTO.getProductId()));
				structuredMoney.setContractNo(mainInfo.getContractNo());
				structuredMoney.setAtomKey(ProductAtomEnum.STRUCTURED_MONEY);
				structuredMoney.setAtomValue(valueOf(calculatorDTO.getStructuredMoney()));
				productParamList.add(structuredMoney);
			}
		});
		basicProductParamService.saveBatch(productParamList);
		return taxRate;
	}
	/**
	 * 保存还款计划表
	 */
	private void saveBasicAssetsRepaymentPlan(RepaymentPlanVO planVo,Long carId,Date date,String contractNo, BigDecimal taxRate) {
		planVo.getCostList().stream().forEach(vo -> {
			String costType = vo.getCostType();
			List<BasicAssetsRepaymentPlan> listPlan = new ArrayList<>();
			vo.getRepaymentList().forEach(info -> {
				BasicAssetsRepaymentPlan repayMentPlan = new BasicAssetsRepaymentPlan();
				repayMentPlan.setContractNo(contractNo);
				repayMentPlan.setCarId(carId);
				repayMentPlan.setAssetType((AssetTypeEnum) AfsEnumUtil.getEnum(costType, AssetTypeEnum.class));
				repayMentPlan.setTermNo(info.getNo());
				repayMentPlan.setRemainPrinciple(info.getYuE());
				repayMentPlan.setReceivableRent(info.getYueGong());
				repayMentPlan.setReceivablePrinciple(info.getBenJin());
				repayMentPlan.setReceivableInterest(info.getLiXi());
				repayMentPlan.setStatus(RepaymentStatusEnum.UNPAID);
				repayMentPlan.setDueDate(DateUtil.offsetMonth(date, info.getNo()));

				//价外税 利息 /（1+税率）*税率
				repayMentPlan.setTax(info.getLiXi().divide(taxRate.add(new BigDecimal(1)),2,4).multiply(taxRate));
				repayMentPlan.setIncome(info.getLiXi().subtract(repayMentPlan.getTax()));
				//乘以100换算为百分数
				repayMentPlan.setRate(taxRate.multiply(new BigDecimal(100)));

				listPlan.add(repayMentPlan);
			});

			basicAssetsRepaymentPlanService.saveBatch(listPlan);// 保存明细还款计划
		});
	}
	/**
	 * 保存还款计划汇总表
	 */
	private List<BasicRepaymentPlan> saveBasicAssetsRepaymentPlanSum(RepaymentPlanVO planVo,Long carId,Date date,String contractNo, BigDecimal taxRate) {
		List<BasicRepaymentPlan> basciPlanList = new ArrayList<>();

		// 借据信息
		BasicDebitInfo debitInfo = new BasicDebitInfo();
		debitInfo.setTotalPrincipal(BigDecimal.ZERO);
		debitInfo.setRemainPrinciple(BigDecimal.ZERO);
		debitInfo.setTotalRent(BigDecimal.ZERO);
		debitInfo.setTotalResidualRent(BigDecimal.ZERO);

		planVo.getRepaymentList().forEach(info -> { // 汇总的还款计划表
			BasicRepaymentPlan basicPlan = new BasicRepaymentPlan();
			basicPlan.setContractNo(contractNo);
			basicPlan.setTermNo(info.getNo());
			basicPlan.setStatus(RepaymentStatusEnum.UNPAID);
			basicPlan.setRemainPrinciple(info.getYuE());
			basicPlan.setReceivableRent(info.getYueGong());
			basicPlan.setReceivablePrinciple(info.getBenJin());
			basicPlan.setReceivableInterest(info.getLiXi());
			basicPlan.setDueDate(DateUtil.offsetMonth(date, info.getNo()));
			//价外税 利息 /（1+税率）*税率
			basicPlan.setTax(info.getLiXi().divide(taxRate.add(new BigDecimal(1)),2,4).multiply(taxRate));
			basicPlan.setIncome(info.getLiXi().subtract(basicPlan.getTax()));
			//乘以100换算为百分数
			basicPlan.setRate(taxRate.multiply(new BigDecimal(100)));

			basciPlanList.add(basicPlan);

			debitInfo.setTotalPrincipal(debitInfo.getTotalPrincipal().add(info.getBenJin()));
			debitInfo.setRemainPrinciple(debitInfo.getRemainPrinciple().add(info.getBenJin()));
			debitInfo.setTotalRent(debitInfo.getTotalRent().add(info.getYueGong()));
			debitInfo.setTotalResidualRent(debitInfo.getTotalResidualRent().add(info.getYueGong()));

		});// 汇总

		basicRepaymentPlanService.saveBatch(basciPlanList); // 保存汇总的还款计划表

		debitInfo.setContractNo(contractNo);
		basicDebitInfoService.save(debitInfo);
		return basciPlanList;
	}
	/**
	 * 保存摊销计划表
	 */
	private Map<Integer, BasicRepaymentPlan> saveAmortizePlan(List<CalculatorDTO> listCalDto,
															  List<BasicRepaymentPlan> basciPlanList,Long carId,Date date,
															  String contractNo) {
		IResponse<RepaymentPlanVO> rsponse = financeCalculatorService.getMultipleAmortizationPlan(listCalDto);
		RepaymentPlanVO rplanVo = rsponse.getData();

		for (AfsRepaymentInfo mentInfo : rplanVo.getRepaymentList()) {

			BasicCostAmortizePlan amortize = new BasicCostAmortizePlan();
			amortize.setPeriod(mentInfo.getNo());
			amortize.setCashFlowCode(CashFlowCodeEnum.DISCOUNT);
			amortize.setContractNo(contractNo);
			amortize.setCashFlowCode(CashFlowCodeEnum.DISCOUNT);
			amortize.setCashFlowName("贴息");
			amortize.setReceivableInterest(mentInfo.getChargeAmortizeAmt()); // 每月摊销金额
			amortize.setRemainAmount(valueOf(mentInfo.getChargeOutstandingAmt()));// 剩余摊销金额
			amortize.setTotalTemainAmount(mentInfo.getCharegOpeningBalAmt()); // 总摊销金额
			amortize.setDueDate(DateUtil.parse(mentInfo.getDueDate()));
			amortizePlanService.save(amortize);
		}

		Map<Integer, BasicRepaymentPlan> rymentMap = basciPlanList.stream()
				.collect(Collectors.toMap(BasicRepaymentPlan::getTermNo,Function.identity()));
		return rymentMap;
	}

	/**
	 * 保存确认收入计划表
	 */
	private void saveBasicInterestAmortizePlan(List<CalculatorDTO> listCalDto, Map<Integer, BasicRepaymentPlan> rymentMap,
												 Long carId,Date date,String contractNo,BigDecimal taxRate) {
		// 调用收入计划表
		IResponse<RepaymentPlanVO> rsponse = financeCalculatorService.getMultipleIncomePlan(listCalDto);

		List<BasicInterestAmortizePlan> interestAmortizePlanList = new ArrayList<>();

		for (AfsRepaymentInfo ment : rsponse.getData().getRepaymentList()) {
			BasicInterestAmortizePlan interAmortizePlan = new BasicInterestAmortizePlan();

			if(DateUtil.thisDayOfMonth() == 1) { //如果是月初 还款计划与收入摊销计划 期数一致
				BasicRepaymentPlan plan = rymentMap.get(ment.getNo());
				interAmortizePlan.setReceivableRent(plan.getReceivableRent());
				interAmortizePlan.setReceivablePrinciple(plan.getReceivablePrinciple());
				interAmortizePlan.setReceivableInterest(plan.getReceivableInterest());
			}else {//不是月初，收入与摊销计划 比还款计划多一期
				BasicRepaymentPlan plan = rymentMap.get(ment.getNo()-1);
				if(!ObjectUtils.isEmpty(plan)) {
					interAmortizePlan.setReceivableRent(plan.getReceivableRent());
					interAmortizePlan.setReceivablePrinciple(plan.getReceivablePrinciple());
					interAmortizePlan.setReceivableInterest(plan.getReceivableInterest());
				}
			}
			interAmortizePlan.setContractNo(contractNo);
			interAmortizePlan.setTermNo(ment.getNo());
			interAmortizePlan.setIncome(ment.getInComAMT());
			interAmortizePlan.setDayNo(ment.getInComeDD().intValue());
			interAmortizePlan.setDueDate(DateUtil.parse(ment.getPostingDate()));
			BigDecimal taxAmt = ment.getInComAMT().divide(taxRate.add(new BigDecimal("1")),2,4).multiply(taxRate).setScale(2,4);
			interAmortizePlan.setTax(taxAmt);
			//把小数乘以100转换成百分数
			interAmortizePlan.setRate(taxRate.multiply(new BigDecimal(100)));
			interestAmortizePlanList.add(interAmortizePlan);
		}
		basicInterestAmortizePlanService.saveBatch(interestAmortizePlanList);
	}

	/**
	 * 保存金融产品，还款计划，摊销计划，收入计划
	 */
	public Long saveAllPlan(ApplyLoanDataMessage entity,DateTime date) {
		Long mainProductId = null;
		ContractMainInfoDTO mainInfo = entity.getMainInfo();

		//融资项信息存储
		List<ContractFinancingItemsDTO> financingItems = entity.getFinancingItems();
		if (!ObjectUtils.isEmpty(financingItems)) {
			List<BasicFinancingItems> financingItemList = (List<BasicFinancingItems>) ApplyLoanDataProcessor
					.converBean(financingItems, BasicFinancingItems.class);
			basicFinancingItemsService.saveBatch(financingItemList);
		}

		//合同金融协议 区分车款和附加贷
		List<ContractFinancialAgreementDTO> fnancialAgreement = entity.getFnancialAgreement();
		if(ObjectUtils.isEmpty(fnancialAgreement)){
			throw new AfsBaseException(MessageFormat.format("未找到合同编号为:[{0}]的金融协议",mainInfo.getContractNo()));
		}
		//金融协议信息存储
		List<BasicFinancialAgreement> fnancialAgreementList = (List<BasicFinancialAgreement>) ApplyLoanDataProcessor
				.converBean(fnancialAgreement, BasicFinancialAgreement.class);
		basicFinancialAgreementService.saveBatch(fnancialAgreementList);


		//按照车辆的维度区分合同金融协议表
		Map<Long, List<BasicFinancialAgreement>> mapList = fnancialAgreementList.stream()
				.collect(Collectors.groupingBy(BasicFinancialAgreement::getCarId));


		BasicPaymentPool pool = new BasicPaymentPool();
		pool.setPaymentAmt(BigDecimal.ZERO);
		Long poolId = uidGenerator.getUID();
		pool.setId(poolId);
		//一合同多车的设计理念，按照车辆维度循环迭代
		for (Entry<Long, List<BasicFinancialAgreement>> s : mapList.entrySet()) {
			Map<String, CalculatorDTO> calculatorDTOs = new HashMap<>();
			//车款和附加贷的还款计划、付款池明细独立存储
			for (BasicFinancialAgreement a : s.getValue()) {
				//处理付款池明细数据
				savePoolDetails(entity, pool, a);
				//处理还款计划计算DTO
				calculatorDTOs = buildCalPlanMap(entity, a,calculatorDTOs);
			}


			ProductInfoDTO productInfoDto = ProductInfoDTO.builder().id(Long.parseLong(calculatorDTOs.get("01").getProductId()))
					.build();
			mainProductId = Long.parseLong(calculatorDTOs.get("01").getProductId());
			IResponse<JSONObject> response = productFeign.queryProductDetails(productInfoDto);
			List<CalculatorDTO> listCalDto = financeCalculatorService.getProductParameter(response.getData(),
					calculatorDTOs.get("01"), calculatorDTOs.get("02"));

			IResponse<RepaymentPlanVO> iresponse = financeCalculatorService.getMultipleRepaymentPlan(listCalDto);
			RepaymentPlanVO planVo = iresponse.getData();
			//顺序要放对，必须让云飞先计算了才可以调用
			BigDecimal taxRate = saveBasicProductParam(calculatorDTOs, entity);
			//taxRate是百分比数据，除以100，换算成小数
			taxRate = taxRate.divide(new BigDecimal(100),6,4);
			//保存还款计划表
			saveBasicAssetsRepaymentPlan(planVo, s.getKey(), date, mainInfo.getContractNo(), taxRate);
			//保存还款计划汇总+借据表
			List<BasicRepaymentPlan> basciPlanList = saveBasicAssetsRepaymentPlanSum(planVo, s.getKey(), date, mainInfo.getContractNo(), taxRate);
			//对listCalDto重新放入批次日期
			List<CalculatorDTO> newListCalDto = new ArrayList();
			for(CalculatorDTO dto : listCalDto){
				CalculatorDTO newDto = new CalculatorDTO();
				BeanUtils.copyProperties(dto, newDto);
				newDto.setActiveDate(DateUtil.formatDateTime(date));
				newListCalDto.add(newDto);
			}
			// 调用费用摊销计划表
			Map<Integer, BasicRepaymentPlan> rymentMap = saveAmortizePlan(newListCalDto, basciPlanList, s.getKey(), date, mainInfo.getContractNo());
			// 调用收入计划表
			saveBasicInterestAmortizePlan(newListCalDto, rymentMap, s.getKey(), date, mainInfo.getContractNo(), taxRate);

			//填入逾期利率  顺序要放对，必须让云飞先计算了才可以调用
			for (BasicFinancialAgreement a : s.getValue()) {
				String overDuebase = calculatorDTOs.get("01").getOverdueBase();
				if(!StringUtils.isEmpty(overDuebase)) {
					a.setOverDueRate(a.getSettleRate().multiply(new BigDecimal(overDuebase)));
					basicFinancialAgreementService.updateById(a);
				}else{
					//TODO 逾期基数处理 李阳
				}
			}
		}

		//存储付款池主表
		savePaymentPool(pool,entity,date,mainInfo.getContractNo());

		//灵活贷款租金调整明细存储
		List<ContractRentAdjustDetailsDTO> rntAdjustDetails = entity.getFinRentAdjustDetailsList();
		if (!ObjectUtils.isEmpty(rntAdjustDetails)) {
			List<BasicRentAdjustDetails> rntAdjustDetailList = (List<BasicRentAdjustDetails>) ApplyLoanDataProcessor
					.converBean(rntAdjustDetails, BasicRentAdjustDetails.class);
			basicRentAdjustDetailsService.saveBatch(rntAdjustDetailList);
		}

		//贴息信息存储
		List<ContractDiscountDetailsDTO> discountDetails = entity.getDiscountDetails();

		if (!ObjectUtils.isEmpty(discountDetails)) {
			List<BasicDiscountDetails> disCountDetails = (List<BasicDiscountDetails>) ApplyLoanDataProcessor
					.converBean(discountDetails, BasicDiscountDetails.class);
			basicDiscountDetailsService.saveBatch(disCountDetails);
		}

		//还款卡信息
		ContractBankCardDTO bankCardDto = entity.getBankCard();

		if (!ObjectUtils.isEmpty(bankCardDto)) {
			BasicBankCard bankCard = (BasicBankCard) ApplyLoanDataProcessor.converBean(bankCardDto, BasicBankCard.class);
			basicBankCardService.save(bankCard);
		}
		return mainProductId;
	}

	/**
	 * 保存付款池主表
	 */
	public void savePaymentPool(BasicPaymentPool pool,ApplyLoanDataMessage entity,Date date,String contractNo) {

		ContractChannelInfoDTO infoDto = applyLoanDataChannelSubHandler.getContractChannelInfoDTO(entity);

		/**  付款池数据基础信息 by ZC.GUO  **/
		pool.setContractNo(contractNo);
		pool.setPaymentStatus(PaymentStatusEnum.waitPayment);
		pool.setReceiptAccount(infoDto.getReceivingAccount());
		pool.setReceiptBankCode(infoDto.getReceivingBank());
		pool.setReceiptEbankCode(infoDto.getElectronicBankNo());
		pool.setReceiptAccountName(infoDto.getReceivingName());
		pool.setIsPaying(YesOrNoEnum.no);
		pool.setRevision(BigDecimal.ZERO.longValue());

		BasicPaymentBank payAccount = basicAutoPaymentConfigService.takePayAccount(pool.getReceiptBankCode());
		if (EmptyUtils.isNotEmpty(payAccount)){
			/**  付款账户信息 by ZC.GUO  **/
			pool.setPaymentBankCode(payAccount.getPaymentBankCode());
			pool.setPaymentAccount(payAccount.getPaymentAccount());
			pool.setPaymentAccountName(payAccount.getPaymentAccountName());

			List<BasicAutoPaymentConfig> payConfigList = autoPaymentConfigService.list();
			BasicAutoPaymentConfig payConfig = null;

			if (EmptyUtils.isNotEmpty(payConfigList)){
				payConfig = payConfigList.get(0);
				/**  付款银行未暂为自动付款银行，使用手动付款，暂不自动付款 by ZC.GUO  **/
				if (Arrays.asList(payConfig.getNoAutoBank().split(",")).contains(pool.getPaymentBankCode())) {
					pool.setPaymentMode(PaymentModeEnum.manualPayment);
					pool.setIsPayment(YesOrNoEnum.no);
				}
				/**  付款银行不属于暂不自动付款银行，使用自动付款，可自动付款 by ZC.GUO  **/
				else{
					pool.setPaymentMode(PaymentModeEnum.autoPayment);
					pool.setIsPayment(YesOrNoEnum.yes);
				}
			}
			/**  自动付款配置无信息，使用手动付款，暂不自动付款 by ZC.GUO  **/
			else{
				pool.setPaymentMode(PaymentModeEnum.manualPayment);
				pool.setIsPayment(YesOrNoEnum.no);
			}
		}
		/**  无对应的付款账号，使用手动付款，暂不自动付款，视为跨行付款 by ZC.GUO  **/
		else{
			pool.setPaymentMode(PaymentModeEnum.manualPayment);
			pool.setIsPayment(YesOrNoEnum.no);
			pool.setIsConglomerate(YesOrNoEnum.yes);
			pool.setPaymentBankCode(null);
			pool.setPaymentAccount(null);
			pool.setPaymentAccountName(null);
		}
		/**  没有对应的付款银行或付款银行与收款银行不一致的视为跨行付款 by ZC.GUO  **/
		if (EmptyUtils.isNotEmpty(pool.getPaymentBankCode()) && pool.getPaymentBankCode().equalsIgnoreCase(pool.getReceiptBankCode())) {
			pool.setIsConglomerate(YesOrNoEnum.no);
		} else {
			pool.setIsConglomerate(YesOrNoEnum.yes);
		}

		paymentPoolService.save(pool);

	}
	/**
	 * 保存付款池明细表
	 */
	public BasicPaymentPool savePoolDetails(ApplyLoanDataMessage entity,BasicPaymentPool pool,
											BasicFinancialAgreement basicFinancialAgreement) {
		ContractMainInfoDTO mainInfo = entity.getMainInfo();

		List<ContractCarDetailsDTO> carDetailList = entity.getCarDetail();
		// 将资产信息List转换为Map
		Map<Long, ContractCarDetailsDTO> carDetailsMap = carDetailList.stream()
				.collect(Collectors.toMap(ContractCarDetailsDTO::getId, Function.identity()));
		if(ObjectUtils.isEmpty(carDetailsMap.get(basicFinancialAgreement.getCarId()))) {
			throw new AfsBaseException(MessageFormat.format("未找到车辆编号为:[{0}]的车辆明细信息",basicFinancialAgreement.getCarId()));
		}
		// 是否需要差额放款
		List<ContractDiscountDetailsDTO> discountDetailList = Optional.ofNullable(entity.getDiscountDetails())
				.orElse(new ArrayList<>());

		ContractChannelInfoDTO infoDto = applyLoanDataChannelSubHandler.getContractChannelInfoDTO(entity);

		// 保存付款池明细记录信息
		BasicPaymentPoolDetails poolDetails = new BasicPaymentPoolDetails(); // 付款池明细数据
		poolDetails.setCarId(basicFinancialAgreement.getCarId());
		poolDetails.setContractNo(mainInfo.getContractNo());
		poolDetails.setCarVin(carDetailsMap.get(basicFinancialAgreement.getCarId()).getCarVin());
		poolDetails.setPaymentType(basicFinancialAgreement.getCostType());
		poolDetails.setPaymentAmt(basicFinancialAgreement.getLoanAmt());
		poolDetails.setPaymentBankCode(""); // 付款银行
		poolDetails.setReceiptBankCode(infoDto.getReceivingBank()); // 收款银行
		poolDetails.setReceiptBankName(""); // 收款银行名称
		poolDetails.setReceiptAccount(infoDto.getReceivingAccount()); // 收款账号
		poolDetails.setReceiptAccountName(infoDto.getReceivingName());// 收款账户名称
		poolDetails.setReceiptEbankCode(infoDto.getElectronicBankNo()); // 联行号
		poolDetails.setDealerId(infoDto.getPartnerCode());
		poolDetails.setDealerName(infoDto.getChannelFullName());
		poolDetails.setStatus(YesOrNoEnum.no);
		poolDetails.setPoolId(valueOf(pool.getId()));
		poolDetailsService.save(poolDetails);
		// 付款池汇总记录
		pool.setPaymentAmt(pool.getPaymentAmt().add(basicFinancialAgreement.getLoanAmt()));

		// 是否需要增加差额放款begin
		if (EmptyUtils.isNotEmpty(discountDetailList)) {
			BigDecimal discountAmtSum = new BigDecimal(0);
			for(ContractDiscountDetailsDTO dto : discountDetailList){
				if(EmptyUtils.isNotEmpty(dto.getTotalToTotal()) && !dto.getTotalToTotal() && basicFinancialAgreement.getId().equals(dto.getCostId())){
					discountAmtSum = discountAmtSum.add(dto.getDiscountAmt());
				}
			}
			if (discountAmtSum.compareTo(BigDecimal.ZERO) > 0) {
				BasicPaymentPoolDetails poolDiscountDetails = new BasicPaymentPoolDetails(); // 付款池明细数据
				poolDiscountDetails.setCarId(basicFinancialAgreement.getCarId());
				poolDiscountDetails.setContractNo(mainInfo.getContractNo());
				poolDiscountDetails.setCarVin(carDetailsMap.get(basicFinancialAgreement.getCarId()).getCarVin());
				poolDiscountDetails.setPaymentType(basicFinancialAgreement.getCostType());
				poolDiscountDetails.setPaymentAmt(discountAmtSum.negate());
				poolDiscountDetails.setPaymentBankCode(""); // 付款银行
				poolDiscountDetails.setReceiptBankCode(infoDto.getReceivingBank()); // 收款银行
				poolDiscountDetails.setReceiptBankName(""); // 收款银行名称
				poolDiscountDetails.setReceiptAccount(infoDto.getReceivingAccount()); // 收款账号
				poolDiscountDetails.setReceiptAccountName(infoDto.getReceivingName());// 收款账户名称
				poolDiscountDetails.setReceiptEbankCode(infoDto.getElectronicBankNo()); // 联行号
				poolDiscountDetails.setDealerId(infoDto.getPartnerCode());
				poolDiscountDetails.setDealerName(infoDto.getChannelFullName());
				poolDiscountDetails.setStatus(YesOrNoEnum.no);
				poolDiscountDetails.setPoolId(valueOf(pool.getId()));
				poolDetailsService.save(poolDiscountDetails);
				// 付款池汇总记录
				pool.setPaymentAmt(pool.getPaymentAmt().add(discountAmtSum.negate()));
			}

		}

		// 是否需要增加差额放款end
		return pool;
	}

	private String valueOf(Object obj){
		return obj == null ? null : String.valueOf(obj);
	}
}
